#region Licence
// Copyright (c) 2007-2008 James Gregory (james@jagregory.com)
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of James Gregory nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

using System.Collections.Generic;
using System.IO;
using JAGregory.NAntTasks;
using NAnt.Core;
using NAnt.Core.Attributes;

namespace JAGregory.NAntTasks
{
    [TaskName("getfilename")]
    public class GetFilenameTask : Task
    {
        private string directoryPath;
        private string property;
        private FileCriteria fileCriteria = FileCriteria.NewestFile;
        private string searchPattern;

        protected override void ExecuteTask()
        {
            FileInfo file = GetFile();

            if (file != null)
                Properties[Property] = file.FullName;
        }

        /// <summary>
        /// Gets the file described in the task.
        /// </summary>
        /// <returns>Found file or null.</returns>
        private FileInfo GetFile()
        {
            List<FileInfo> files = GetSortedFiles();

            if (files.Count == 0) return null;

            if (fileCriteria == FileCriteria.FirstFile || fileCriteria == FileCriteria.FirstModifiedFile || fileCriteria == FileCriteria.NewestFile)
                return files[0];
            else
                return files[files.Count - 1];
        }

        /// <summary>
        /// Gets all the files in the specified directory, matching the search pattern, sorted by
        /// what was described in the file criteria.
        /// </summary>
        /// <returns>Sorted list of files</returns>
        private List<FileInfo> GetSortedFiles()
        {
            DirectoryInfo dir = new DirectoryInfo(DirectoryPath);
            List<FileInfo> files = new List<FileInfo>(dir.GetFiles(SearchPattern));

            if (fileCriteria != FileCriteria.FirstFile && fileCriteria != FileCriteria.LastFile)
            {
                files.Sort(delegate(FileInfo a, FileInfo b) {
                    switch (fileCriteria)
                    {
                        case FileCriteria.FirstModifiedFile:
                        case FileCriteria.LastModifiedFile:
                            return a.LastWriteTime.CompareTo(b.LastWriteTime);
                        default:
                        case FileCriteria.NewestFile:
                        case FileCriteria.OldestFile:
                            return a.CreationTime.CompareTo(b.CreationTime);
                    }
                });
            }

            return files;
        }

        [TaskAttribute("in", Required = true)]
        [StringValidator(AllowEmpty = false)]
        public string DirectoryPath
        {
            get { return directoryPath; }
            set { directoryPath = value; }
        }

        [TaskAttribute("searchPattern")]
        public string SearchPattern
        {
            get { return searchPattern; }
            set { searchPattern = value; }
        }

        [TaskAttribute("property", Required = true)]
        [StringValidator(AllowEmpty = false)]
        public string Property
        {
            get { return property; }
            set { property = value; }
        }

        [TaskAttribute("of")]
        [StringValidator(Expression = "^(FirstModifiedFile|LastModifiedFile|NewestFile|OldestFile|FirstFile|LastFile)$", ExpressionErrorMessage = "Can only be one of: FirstModifiedFile, LastModifiedFile, NewestFile, OldestFile, FirstFile, or LastFile.")]
        public FileCriteria FileCriteria
        {
            get { return fileCriteria; }
            set { fileCriteria = value; }
        }
    }
}